<template>
  <div class="page-container">
    <el-form
      ref="dataForm"
      label-width="140px"
      :model="formData"
      class="fit-box full-height"
      :rules="rules"
    >
      <el-tabs v-model="tabName" class="fit-box full-height" @tabClick="changeTab">
        <el-tab-pane name="form" label="基础信息" class="fit-box full-height">
          <div style="width: 400px">
            <el-row>
              <el-col :span="24">
                <el-form-item label="表单名称" prop="name">
                  <el-input v-model="formData.name" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="24">
                <el-form-item label="布局方式" prop="layoutType">
                  <ac-buttons v-model="formData.layoutType" options="自动" />
                  <ac-icon
                    v-if="formData.layoutType === '自定义'"
                    iconId="018dca6db20c6a3aaf68"
                    style="margin-left: 10px;"
                  />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row v-if="formData.layoutType === '自动'">
              <el-col :span="24">
                <el-form-item label="显示方式" prop="showModel">
                  <ac-buttons v-model="formData.showModel" options="普通,标签,分割线" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row v-if="formData.layoutType === '自动'">
              <el-col :span="24" v-if="formData.showModel === '分割线'">
                <el-form-item label="分割线样式" prop="dividerStyle">
                  <ac-buttons v-model="formData.dividerStyle" options="无,实线,虚线,标签" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row v-if="formData.layoutType === '自动'">
              <el-col :span="24" v-if="formData.showModel === '分割线'">
                <el-form-item label="内容位置" prop="dividerPosition">
                  <ac-buttons v-model="formData.dividerPosition" options="居左,居中,居右" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row v-if="formData.layoutType === '自动'">
              <el-col :span="24">
                <el-form-item label="批量编辑" prop="batchEdit">
                  <ac-dict-switch v-model="formData.batchEdit" dictCode="dictYesNo" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row v-if="formData.layoutType === '自动' && formData.batchEdit === '1'">
              <el-col :span="24">
                <el-form-item label="显示操作按钮" prop="showOperateButton">
                  <ac-dict-switch v-model="formData.showOperateButton" dictCode="dictYesNo" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row v-if="formData.layoutType === '自动' && formData.batchEdit === '1'">
              <el-col :span="24">
                <el-form-item label="是否必填" prop="required">
                  <ac-dict-switch v-model="formData.required" dictCode="dictYesNo" />
                </el-form-item>
              </el-col>
            </el-row>
            <el-row>
              <el-col :span="24">
                <el-form-item label="初始化脚本" prop="initScriptId">
                  <ac-tree
                    v-model="formData.initScriptId"
                    data-url="/system/scriptGroovy/queryTree"
                    type-select="script"
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </div>
        </el-tab-pane>
        <el-tab-pane
          v-if="formData.layoutType === '自动'"
          name="field"
          label="表单字段"
          class="fit-box full-height"
          style="padding-right: 5px;overflow: auto"
        >
          <el-row v-if="formData.batchEdit !== '1'">
            <el-col :span="24">
              <el-button
                type="success"
                @click="addModel"
              >添加分段</el-button>
            </el-col>
          </el-row>
          <el-row
            v-for="(model, index) in formData.modelList"
            :key="index"
            style="margin-top: 15px;"
          >
            <el-col :span="24">
              <el-row>
                <el-col :span="5">
                  <el-form-item label="分段名称">
                    <el-input v-model="model.name" />
                  </el-form-item>
                </el-col>
                <el-col :span="4" v-if="formData.batchEdit !== '1'">
                  <el-form-item label="标签宽度" prop="labelWidth">
                    <ac-number v-model="model.labelWidth" :point="0" />
                  </el-form-item>
                </el-col>
                <el-col :span="4" v-if="formData.batchEdit !== '1'">
                  <el-form-item label="对齐方式" prop="labelAlign">
                    <ac-select v-model="model.labelAlign" options="居左,居中,居右" />
                  </el-form-item>
                </el-col>
                <el-col :span="4">
                  <el-form-item label="排序" prop="ordinal" label-width="80">
                    <ac-number v-model="model.ordinal" :point="0" />
                  </el-form-item>
                </el-col>
                <el-col :span="formData.batchEdit !== '1' ? 7 : 15" style="text-align: right;">
                  <el-button
                    v-if="(!sortableInst || sortingId !== (model.id || model.rowFlag))
                      && (model.fieldList || []).length > 1"
                    type="primary"
                    @click="sortDataField(model)"
                  >开启排序</el-button>
                  <el-button
                    v-if="sortableInst && sortingId === (model.id || model.rowFlag)"
                    type="info"
                    @click="unSortDataField"
                  >关闭排序</el-button>
                  <el-button
                    type="success"
                    @click="addModelField(model)"
                  >添加字段</el-button>
                  <el-button
                    v-if="formData.batchEdit !== '1'"
                    type="danger"
                    @click="deleteModel(model)"
                  >删除分段</el-button>
                </el-col>
              </el-row>
              <el-table
                :ref="el => setRefs(el, model)"
                :show-overflow-tooltip="false"
                tooltip-effect="light"
                class="field-table edit-table"
                style="margin-bottom: 20px"
                width="100%"
                :row-key="getFieldRowKey"
                :data="model.fieldList"
                :border="true"
                :stripe="false"
              >
                <el-table-column
                  header-align="center"
                  align="center"
                  label="字段名称"
                  :min-width="120"
                  prop="fieldName"
                />
                <el-table-column
                  header-align="center"
                  label="显示名称"
                  :min-width="120"
                  prop="aliasName"
                >
                  <template #default="scope">
                    <el-input v-model="scope.row.aliasName" />
                  </template>
                </el-table-column>
                <el-table-column
                  header-align="center"
                  align="center"
                  label="标签颜色"
                  width="100"
                  prop="labelColor"
                >
                  <template #default="scope">
                    <el-color-picker v-model="scope.row.labelColor" />
                  </template>
                </el-table-column>
                <el-table-column
                  header-align="center"
                  label="默认值"
                  :min-width="120"
                  prop="defaultValue"
                >
                  <template #header>
                    <span style="margin-right: 5px">默认值</span>
                    <ac-default-value-tips />
                  </template>
                  <template #default="scope">
                    <ac-input
                      v-if="scope.row.manually === '1'"
                      v-model="scope.row.defaultValue"
                    />
                    <component
                      v-else-if="getComponent(scope.row.fieldName) !== 'ac-affix'
                        && getComponent(scope.row.fieldName) !== 'ac-image'
                        && getComponent(scope.row.fieldName) !== 'ac-video'"
                      v-model="scope.row.defaultValue"
                      :is="getComponent(scope.row.fieldName)"
                      v-bind="getOptions(scope.row.fieldName)"
                    />
                    <ac-dict-switch
                      v-if="getComponent(scope.row.fieldName) !== 'ac-affix'
                        && getComponent(scope.row.fieldName) !== 'ac-image'
                        && getComponent(scope.row.fieldName) !== 'ac-video'"
                      v-model="scope.row.manually"
                      dictCode="dictYesNo"
                      style="margin: 0 5px;"
                      title="手动录入"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  header-align="center"
                  :width="100"
                  prop="colCnt"
                >
                  <template #header>
                    <div v-if="formData.batchEdit !== '1'">
                      <span style="margin-right: 5px">所占列数</span>
                      <el-tooltip content="每行切分为24列">
                        <ac-icon iconId="018dca8ec9890493be26" />
                      </el-tooltip>
                    </div>
                    <div v-else>
                      <span style="margin-right: 5px">列宽</span>
                      <el-tooltip content="0时为自动宽度,负数时为最小宽度">
                        <ac-icon iconId="018dca8ec9890493be26" />
                      </el-tooltip>
                    </div>
                  </template>
                  <template #default="scope">
                    <ac-number
                      v-model="scope.row.colCnt"
                      :point="0"
                      :min="formData.batchEdit !== '1' ? 0 : -200"
                    />
                  </template>
                </el-table-column>
                <el-table-column
                  header-align="center"
                  label="字段说明"
                  :min-width="120"
                  prop="description"
                >
                  <template #default="scope">
                    <el-input v-model="scope.row.description" />
                  </template>
                </el-table-column>
                <el-table-column
                  header-align="center"
                  align="center"
                  label="是否只读"
                  :width="80"
                  prop="readonly"
                >
                  <template #default="scope">
                    <ac-dict-switch v-model="scope.row.readonly" dictCode="dictYesNo" />
                  </template>
                </el-table-column>
                <el-table-column
                  header-align="center"
                  align="center"
                  label="是否必填"
                  :width="80"
                  prop="required"
                >
                  <template #default="scope">
                    <ac-dict-switch v-model="scope.row.required" dictCode="dictYesNo" />
                  </template>
                </el-table-column>
                <el-table-column
                  header-align="center"
                  align="center"
                  label="是否隐藏"
                  :width="80"
                  prop="hide"
                >
                  <template #default="scope">
                    <ac-dict-switch v-model="scope.row.hide" dictCode="dictYesNo" />
                  </template>
                </el-table-column>
                <el-table-column
                  header-align="center"
                  align="center"
                  label="操作"
                  :width="120"
                  prop="ordinal"
                >
                  <template #default="scope">
                    <el-button
                      v-if="canFilter(scope.row.fieldName)"
                      type="primary"
                      @click="editFieldDialog(scope.row)"
                      link
                    >选择配置</el-button>
                    <el-button
                      type="danger"
                      @click="deleteModelField(model, scope.row)"
                      link
                    >删除</el-button>
                  </template>
                </el-table-column>
              </el-table>
            </el-col>
          </el-row>
        </el-tab-pane>
        <el-tab-pane
          name="autofill"
          label="自动填充"
          class="fit-box full-height"
          style="padding-right: 5px;overflow: auto"
        >
          <el-row>
            <el-col :span="24">
              <el-button
                type="success"
                @click="addAutofill"
              >添加自动填充</el-button>
            </el-col>
          </el-row>
          <el-row v-for="(autofill, index) in formData.autofillList" :key="index">
            <el-col :span="24">
              <el-divider />
              <el-row>
                <el-col :span="6">
                  <el-form-item label="触发字段" prop="triggerFieldName">
                    <ac-select v-model="autofill.triggerFieldName" :options="fieldNameOptions" />
                  </el-form-item>
                </el-col>
                <el-col :span="6">
                  <el-form-item label="来源数据模型" prop="dataModelId">
                    <ac-tree
                      v-model="autofill.dataModelId"
                      data-url="/system/dataModel/queryTree"
                      type-select="model"
                      @change="changeDataModel(autofill)"
                    />
                  </el-form-item>
                </el-col>
                <el-col :span="6">
                  <el-form-item label="匹配字段" prop="compareFieldName">
                    <ac-select v-model="autofill.compareFieldName" :options="autofill.dataModelFieldOptions"/>
                  </el-form-item>
                </el-col>
                <el-col :span="6" style="text-align: right">
                  <el-button
                    type="success"
                    @click="addAutofillField(autofill)"
                  >添加填充字段</el-button>
                  <el-button
                    type="danger"
                    @click="deleteAutofill(autofill)"
                  >删除自动填充</el-button>
                </el-col>
              </el-row>
              <el-row v-for="(field, index2) in autofill.fieldList" :key="index2">
                <el-col :span="6">
                  <el-form-item label="填充字段" prop="autofillFieldName">
                    <ac-select v-model="field.autofillFieldName" :options="fieldNameOptions" />
                  </el-form-item>
                </el-col>
                <el-col :span="6">
                  <el-form-item label="来源字段" prop="sourceFieldName">
                    <ac-select v-model="field.sourceFieldName" :options="autofill.dataModelFieldOptions"/>
                  </el-form-item>
                </el-col>
                <el-col :span="12" style="text-align: right">
                  <el-button
                    type="danger"
                    @click="deleteAutofillField(autofill, field)"
                  >删除填充字段</el-button>
                </el-col>
              </el-row>
            </el-col>
          </el-row>
        </el-tab-pane>
        <el-tab-pane
          name="display"
          label="显隐禁用"
          class="fit-box full-height"
          style="padding-right: 5px;overflow: auto"
        >
          <el-row>
            <el-col :span="24">
              <el-button
                type="success"
                @click="addDisplay"
              >添加显隐禁用</el-button>
            </el-col>
          </el-row>
          <el-row v-for="(display, index3) in formData.displayList" :key="index3">
            <el-col :span="24">
              <el-divider />
              <el-row>
                <el-col :span="5">
                  <el-form-item label="操作字段" prop="fieldName">
                    <ac-select v-model="display.fieldName" :options="fieldNameOptions" />
                  </el-form-item>
                </el-col>
                <el-col :span="8">
                  <el-form-item label="显隐类型" prop="type">
                    <ac-buttons v-model="display.type" options="显示,隐藏,禁用" />
                  </el-form-item>
                </el-col>
                <el-col :span="11" style="text-align: right">
                  <el-button
                    type="success"
                    @click="addDisplayRule(display)"
                  >添加条件</el-button>
                  <el-button
                    type="danger"
                    @click="deleteDisplay(display)"
                  >删除显隐禁用</el-button>
                </el-col>
              </el-row>
              <el-row v-for="(rule, index4) in display.ruleList" :key="index4">
                <el-col :span="5">
                  <el-form-item label="条件分组" prop="grouping">
                    <template #label>
                      <span style="margin-right: 5px">条件分组</span>
                      <el-tooltip content="同一分组为 and 条件，不同分组间为 or 条件">
                        <ac-icon iconId="018dca8ec9890493be26" />
                      </el-tooltip>
                    </template>
                    <ac-number v-model="rule.grouping" :point="0" />
                  </el-form-item>
                </el-col>
                <el-col :span="5">
                  <el-form-item label="条件字段" prop="fieldName">
                    <ac-select v-model="rule.fieldName" :options="fieldNameOptions"/>
                  </el-form-item>
                </el-col>
                <el-col :span="5">
                  <el-form-item label="条件类型" prop="type">
                    <ac-select v-model="rule.type" options="包含,不包含,等于,不等于,大于,大于等于,小于,小于等于" />
                  </el-form-item>
                </el-col>
                <el-col :span="5">
                  <el-form-item label="条件值" prop="value">
                    <component
                      v-model="rule.value"
                      :is="getComponent(rule.fieldName)"
                      v-bind="getOptions(rule.fieldName)"
                    />
                  </el-form-item>
                </el-col>
                <el-col :span="4" style="text-align: right">
                  <el-button
                    type="danger"
                    @click="deleteDisplayRule(display, rule)"
                  >删除条件</el-button>
                </el-col>
              </el-row>
            </el-col>
          </el-row>
        </el-tab-pane>
        <el-tab-pane name="tips" label="提示信息" class="fit-box full-height">
          <el-row>
            <el-col :span="6">
              <el-form-item label="位置" prop="tipsPosition" label-width="80">
                <ac-buttons v-model="formData.tipsPosition" options="顶部,底部" />
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="来源" prop="tipsOrigin" label-width="80">
                <ac-buttons v-model="formData.tipsOrigin" options="输入,脚本" />
              </el-form-item>
            </el-col>
            <el-col :span="6" v-if="formData.tipsOrigin === '脚本'">
              <el-form-item label="脚本" prop="tipsScriptId" label-width="80">
                <ac-tree
                  v-model="formData.tipsScriptId"
                  data-url="/system/scriptGroovy/queryTree"
                  type-select="script"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <ac-rich-editor v-if="formData.tipsOrigin === '输入'" v-model="formData.tipsHtml" />
        </el-tab-pane>
        <el-tab-pane name="script" label="页面脚本" class="fit-box full-height">
          <template #label>
            <span style="margin-right: 5px">页面脚本</span>
            <el-tooltip>
              <template #content>
                <el-input
                  v-model="scriptTips"
                  class="script-tips-box"
                  type="textarea"
                  readonly
                  resize="none"
                />
              </template>
              <ac-icon iconId="018dca8ec9890493be26" />
            </el-tooltip>
          </template>
          <div class="script-box">
            <div class="script-left-box">
              <ac-code
                ref="codeRef"
                v-model="formData.scriptContent"
                :fullscreen="false"
                title="页面脚本"
                mode="javascript"
              />
            </div>
            <div class="script-right-box">
              <div class="field-box">
                <div
                  v-for="field in fieldList"
                  :key="field.fieldName"
                  class="field-item"
                >{{field.showName}}【{{field.fieldName}}】: {{field.fieldType}}</div>
              </div>
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </el-form>
  </div>

  <!-- 添加字段 -->
  <el-dialog
    v-model="fieldAddVisible"
    title="添加字段"
    class="no-padding"
    :close-on-click-modal="false"
    destroy-on-close
    fullscreen
    draggable
  >
    <div class="page-container">
      <el-table
        ref="fieldAddTable"
        :show-overflow-tooltip="false"
        tooltip-effect="light"
        class="field-table fit-table"
        width="100%"
        @row-click="rowClick"
        :data="fieldList"
        :border="true"
        :stripe="false"
      >
        <el-table-column
          header-align="center"
          align="center"
          type="selection"
          width="55"
        />
        <el-table-column
          header-align="center"
          label="字段名称"
          :min-width="120"
          prop="fieldName"
          sortable
        />
        <el-table-column
          header-align="center"
          label="显示名称"
          :min-width="120"
          prop="showName"
          sortable
        />
        <el-table-column
          header-align="center"
          align="center"
          label="是否主键"
          :width="100"
          prop="primaryKey"
        >
          <template #default="scope">
            <ac-dict-radio showText v-model="scope.row.primaryKey" dictCode="dictYesNo" />
          </template>
        </el-table-column>
        <el-table-column
          header-align="center"
          align="center"
          label="字段类型"
          :width="120"
          prop="fieldType"
        />
        <el-table-column
          header-align="center"
          align="center"
          label="是否必填"
          :width="100"
          prop="required"
        >
          <template #default="scope">
            <ac-dict-radio showText v-model="scope.row.required" dictCode="dictYesNo" />
          </template>
        </el-table-column>
      </el-table>
    </div>
    <template #footer>
      <el-button
        size="default"
        type="info"
        @click="fieldAddVisible=false"
      >取消</el-button>
      <el-button
        type="primary"
        size="default"
        @click="submitFieldAddForm"
      >确定</el-button>
    </template>
  </el-dialog>

  <!-- 编辑字段 -->
  <el-dialog
    v-model="fieldVisible"
    width="650px"
    title="选择配置"
    class="no-padding"
    :close-on-click-modal="false"
    destroy-on-close
    draggable
  >
    <div class="page-container">
      <el-form
        ref="fieldForm"
        label-width="130px"
        :model="fieldData"
        style="height: 100%;"
      >
        <el-row>
          <el-col :span="22">
            <el-form-item label="选择方式" prop="choose">
              <ac-radio v-model="fieldData.choose" options="下拉框,弹窗" @change="changeChoose" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="fieldData.choose === '弹窗'">
          <el-col :span="22">
            <el-form-item label="弹窗页面" prop="pageId">
              <ac-tree
                v-model="fieldData.pageId"
                data-url="/system/page/queryTree"
                typeSelect="page"
                @change="changePage"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row
          v-if="fieldData.choose === '弹窗'
            && fieldData.pageId
            && fieldData.paramList
            && fieldData.paramList.length > 0"
        >
          <el-col :span="22">
            <el-form-item
              v-if="fieldData.paramList && fieldData.paramList.length > 0"
              label="出参配置"
              prop="pageId"
            >
              <div style="display: flex;flex-direction: column">
                <div
                  class="param-item"
                  v-for="(param, index) in fieldData.paramList"
                  :key="index"
                >
                  <div class="param-field">
                    <ac-select
                      v-if="!param.manually"
                      v-model="param.fieldId"
                      :options="fieldIdOptions"
                      allow-create
                    />
                    <ac-input v-if="param.manually" v-model="param.filterValue" />
                    <ac-switch
                      style="margin-left: 5px"
                      v-model="param.manually"
                      :options="[{key: true, value: ''}, {key: false, value: ''}]"
                    />
                  </div>
                  <div class="param-split"><ac-icon iconId="018eecae20bd010c2adf" /></div>
                  <div class="param-page">
                    <el-input v-model="param.pageParamName" disabled />
                  </div>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="fieldData.choose === '弹窗'">
          <el-col :span="22">
            <el-form-item label="全屏弹窗" prop="fullscreen">
              <ac-dict-switch v-model="fieldData.fullscreen" dictCode="dictYesNo" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row v-if="fieldData.choose === '弹窗'">
          <el-col :span="22" v-if="fieldData.fullscreen !== '1'">
            <el-form-item label="弹窗大小" prop="width">
              <ac-number v-model="fieldData.width" :point="0" />
            </el-form-item>
          </el-col>
        </el-row>
        <div v-if="fieldData.choose === '下拉框'">
          <el-row>
            <el-col :span="22">
              <el-form-item label="参数配置">
                <el-button type="success" @click="addFieldFilter">添加过滤参数</el-button>
                <div style="display: flex;flex-direction: column;margin-top: 5px;">
                  <div
                    class="param-item"
                    v-for="(param, index) in fieldData.filterList"
                    :key="index"
                  >
                    <div class="param-field">
                      <ac-select
                        v-if="!param.manually"
                        v-model="param.filterValueFieldId"
                        :options="fieldIdOptions"
                      />
                      <ac-input v-if="param.manually" v-model="param.filterValue" />
                      <ac-switch
                        style="margin-left: 5px"
                        v-model="param.manually"
                        :options="[{key: true, value: ''}, {key: false, value: ''}]"
                      />
                    </div>
                    <div class="param-split"><ac-icon iconId="018eecae20bd010c2adf" /></div>
                    <div class="param-page">
                      <ac-select
                        v-model="param.filterFieldId"
                        :options="filterFieldIdOptions"
                      />
                    </div>
                    <div style="margin-left: 5px;cursor: pointer">
                      <ac-icon
                        size="14"
                        color="red"
                        iconId="018dc9c3efd3a0502886"
                        title="删除"
                        @click.stop="deleteFieldFilter(index)"
                      />
                    </div>
                  </div>
                </div>
              </el-form-item>
            </el-col>
          </el-row>
        </div>
      </el-form>
    </div>
    <template #footer>
      <el-button
        size="default"
        type="info"
        @click="fieldVisible=false"
      >取消</el-button>
      <el-button
        type="primary"
        size="default"
        @click="submitFieldForm"
      >确定</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, onMounted, watch, nextTick } from 'vue';
import api from "@/http/api";
import { ElMessage, ElMessageBox } from "element-plus";
import tool from "@/utils/tool";
import Sortable from "sortablejs";
import loading from '@/utils/loading';

const emit = defineEmits(['afterSubmit'])
const props = defineProps({
  options: {
    type: Object,
    default: () => {
    }
  }
});

const tabName = ref('form');
const formData = ref({});
const dataForm = ref();
const scriptTips = ref('');
const codeRef = ref();
const rowFlag = ref(0);

const fieldList = ref([]);
const fieldIdOptions = ref([]);
const fieldNameOptions = ref([]);

const fieldAddVisible = ref(false);
const fieldAddTable = ref();
const currModel = ref();

const fieldVisible = ref(false);
const fieldForm = ref();
const fieldData = ref({});

const modelRefs = ref([]);
const sortingId = ref();
const sortableInst = ref();

const rules = ref({
  name: [
    {required: true, message: '表单名称不能为空！'},
    {max: 100, message: '长度必须小于等于 100 个字符！', trigger: ['change', 'blur']}
  ],
});

const init = (options) => {
  formData.value = {
    id: options.id || '',
    layoutType: '自动',
    showModel: '普通',
    batchEdit: '0',
    showOperateButton: '1',
    modelId: options.modelId || '',
    modelList: [{
      name: '',
      labelAlign: '居右',
      labelWidth: 120,
      fieldList: [],
      rowFlag: ++rowFlag.value
    }]
  };
  loadDataForm(options.id);
  loadDataField(options.modelId || '-1');
};

const loadDataForm = (id) => {
  if (id) {
    loading.showLoading();
    api.post('/system/dataForm/queryBy', {id: id}).then(res => {
      const data = res.data || {};
      (data.autofillList || []).forEach(autofill => changeDataModel(autofill));
      formData.value = data;
      loading.hideLoading();
    }).catch(() => loading.hideLoading());
  }
};

const getFieldRowKey = row => {
  return row.id || row.rowFlag;
};

const setRefs = (el, model) => {
  if (el) {
    modelRefs.value['modelTable_' + (model.id || model.rowFlag)] = el;
  }
};

const sortDataField = (model) => {
  if (sortableInst.value) {
    sortableInst.value.destroy();
  }

  const ref = modelRefs.value['modelTable_' + (model.id || model.rowFlag)];
  if (ref) {
    const el = ref.$el.querySelector(".el-table__body-wrapper tbody");
    sortableInst.value = Sortable.create(el, {
      handle: '.el-table__row',
      onEnd: ({newIndex, oldIndex}) => {
        const list = tool.deepClone(model.fieldList);
        const currRow = list.splice(oldIndex, 1)[0];
        list.splice(newIndex, 0, currRow);
        nextTick(() => {
          model.fieldList = list;
        });
      }
    });
    sortingId.value = model.id || model.rowFlag;
  }
};

const unSortDataField = () => {
  if (sortableInst.value) {
    sortableInst.value.destroy();
  }
  sortableInst.value = null;
};

const addModel = () => {
  if (!formData.value.modelList) {
    formData.value.modelList = [];
  }

  formData.value.modelList.push({
    name: '',
    labelWidth: 120,
    labelAlign: '居右',
    fieldList: [],
    rowFlag: ++rowFlag.value
  });
};

const deleteModel = (data) => {
  ElMessageBox.confirm('请确认是否删除' + (data.name ? ('【' + data.name + '】') : '') + '？', '提示', {type: 'warning'}).then(() => {
    const index = formData.value.modelList
      .findIndex(item => data.id ? item.id === data.id : item.rowFlag === data.rowFlag);
    formData.value.modelList.splice(index, 1);
  }).catch(() => {});
};

const changeTab = (tabName) => {
  if (tabName.paneName === 'script') {
    codeRef.value && codeRef.value.refresh();
  }
};

const rowClick = (row) => {
  fieldAddTable.value.toggleRowSelection(row);
};

const addModelField = (model) => {
  currModel.value = model;
  fieldAddVisible.value = true;
};

const submitFieldAddForm = () => {
  if (!currModel.value) {
    return;
  }

  fieldAddTable.value.getSelectionRows().forEach(row => {
    if (currModel.value.fieldList.findIndex(item => item.fieldId === row.id) < 0) {
      const data = tool.deepClone(row);
      data.id = null;
      data.rowFlag = ++rowFlag.value;
      data.fieldId = row.id;
      data.fieldName = row.fieldName;
      data.aliasName = row.showName;
      data.defaultValue = row.defaultValue;
      data.labelColor = '';
      data.colCnt = formData.value.batchEdit === '1' ? 120 : 11;
      data.hide = '0';
      data.required = row.required;
      currModel.value.fieldList.push(data);
    }
  });
  fieldAddVisible.value = false;
  currModel.value = null;
};

const canFilter = (fieldName) => {
  const field = fieldList.value.find(item => item.fieldName === fieldName);
  return !!(field
    && field.fieldType === '联动'
    && (field.relevanceType === '数据模型' || field.relevanceType.includes("字典")));
};

const currField = ref({});
const rowFieldFlag = ref(1);
const filterFieldIdOptions = ref([]);
const editFieldDialog = (data) => {
  currField.value = data;
  fieldData.value = data.dialogJson ? JSON.parse(data.dialogJson) : {choose: '弹窗', fullscreen: '1'};
  fieldData.value.pageId = fieldData.value.pageId || data.dialogPageId || '';
  fieldVisible.value = true;
  filterFieldIdOptions.value = [];

  (fieldData.value.filterList || []).forEach(item => {
    item.rowFlag = rowFlag.value++;
  });
  changeChoose();
};

const changeChoose = () => {
  if (fieldData.value.choose === '弹窗') {
    changePage();
  } else {
    loadFieldDataField();
  }
};

const changePage = () => {
  if (!fieldData.value.pageId) {
    fieldData.value.paramList = [];
    return;
  }

  api.post('/system/pageParam/queryList', {pageId: fieldData.value.pageId}).then(res => {
    const pageParamList = res.data || [];
    const paramList = fieldData.value.paramList || [];
    pageParamList.forEach(pageParam => {
      const fieldParam = paramList.find(item => item.pageParamId === pageParam.id);
      if (fieldParam) {
        fieldParam.pageParamName = pageParam.name;
      } else {
        paramList.push({pageParamId: pageParam.id, pageParamName: pageParam.name});
      }
    });

    fieldData.value.paramList = paramList.filter(param => pageParamList.find(item => item.id === param.pageParamId));
  });
};

const loadFieldDataField = () => {
  const field = fieldList.value.find(item => item.id === currField.value.fieldId);

  if (field && field.relevanceType.includes("字典")) {
    filterFieldIdOptions.value.push({key: 'pid', value: '父键'});
  } else if (field && field.relevanceList && field.relevanceList.length > 0) {
    const modelId = field.relevanceList[field.relevanceList.length - 1].dataModelId;
    api.post('/system/dataField/queryList', {modelId: modelId}).then(res => {
      (res.data || []).forEach(fieldItem => {
        filterFieldIdOptions.value.push({key: fieldItem.id, value: fieldItem.showName});
      });
    });
  }
};

const addFieldFilter = () => {
  if (!fieldData.value.filterList) {
    fieldData.value.filterList = [];
  }
  fieldData.value.filterList.push({rowFlag: rowFieldFlag.value++, manually: false});
};

const deleteFieldFilter = (index) => {
  if (!fieldData.value.filterList) return;
  fieldData.value.filterList.splice(index, 1);
};

const submitFieldForm = () => {
  const result = {choose: fieldData.value.choose};
  if (result.choose === '弹窗') {
    currField.value.dialogPageId = fieldData.value.pageId;

    result.pageId = fieldData.value.pageId;
    result.fullscreen = fieldData.value.fullscreen;
    result.width = fieldData.value.width;
    result.paramList = fieldData.value.paramList.map(param => {
      if (param.manually) {
        return {
          manually: param.manually,
          fieldId: param.fieldId,
          filterValue: param.filterValue,
          pageParamId: param.pageParamId,
          pageParamName: param.pageParamName
        }
      } else {
        const field = fieldList.value.find(item => item.id === param.fieldId);
        return {
          manually: param.manually,
          fieldId: param.fieldId,
          fieldName: field ? field.fieldName : '',
          pageParamId: param.pageParamId,
          pageParamName: param.pageParamName
        }
      }
    });
  } else {
    currField.value.dialogPageId = null;
    result.filterList = fieldData.value.filterList;
  }

  currField.value.dialogJson = JSON.stringify(result);
  fieldVisible.value = false;
};

const deleteModelField = (model, data) => {
  ElMessageBox.confirm('请确认是否删除【' + data.aliasName + '】？', '提示', {type: 'warning'}).then(() => {
    const index = model.fieldList
      .findIndex(item => item.id ? item.id === data.id : item.rowFlag === data.rowFlag);
    model.fieldList.splice(index, 1);
  }).catch(() => {});
};

const addAutofill = () => {
  if (!formData.value.autofillList) {
    formData.value.autofillList = [];
  }

  formData.value.autofillList.push({
    name: '',
    rowFlag: ++rowFlag.value,
    fieldList: [{rowFlag: ++rowFlag.value}]
  });
};

const deleteAutofill = (data) => {
  ElMessageBox.confirm('请确认是否删除？', '提示', {type: 'warning'}).then(() => {
    const index = formData.value.autofillList
      .findIndex(item => data.id ? item.id === data.id : item.rowFlag === data.rowFlag);
    formData.value.autofillList.splice(index, 1);
  }).catch(() => {});
};

const changeDataModel = (autofill) => {
  autofill.dataModelFieldOptions = [];

  if (autofill.dataModelId) {
    api.post('/system/dataField/queryList', {modelId: autofill.dataModelId}).then(res => {
      const options = [];
      (res.data || []).forEach(field => options.push({key: field.fieldName, value: field.showName}));
      autofill.dataModelFieldOptions = options;
    });
  }
};

const addAutofillField = (autofill) => {
  if (!autofill.fieldList) {
    autofill.fieldList = [];
  }

  autofill.fieldList.push({
    rowFlag: ++rowFlag.value
  });
};

const deleteAutofillField = (autofill, data) => {
  ElMessageBox.confirm('请确认是否删除？', '提示', {type: 'warning'}).then(() => {
    const index = autofill.fieldList
      .findIndex(item => item.id ? item.id === data.id : item.rowFlag === data.rowFlag);
    autofill.fieldList.splice(index, 1);
  }).catch(() => {});
};

const addDisplay = () => {
  if (!formData.value.displayList) {
    formData.value.displayList = [];
  }

  formData.value.displayList.push({
    name: '',
    rowFlag: ++rowFlag.value,
    ruleList: [{rowFlag: ++rowFlag.value}]
  });
};

const deleteDisplay = (data) => {
  ElMessageBox.confirm('请确认是否删除？', '提示', {type: 'warning'}).then(() => {
    const index = formData.value.displayList
      .findIndex(item => data.id ? item.id === data.id : item.rowFlag === data.rowFlag);
    formData.value.displayList.splice(index, 1);
  }).catch(() => {});
};

const addDisplayRule = (display) => {
  if (!display.fieldList) {
    display.fieldList = [];
  }

  display.ruleList.push({
    rowFlag: ++rowFlag.value
  });
};

const deleteDisplayRule = (display, data) => {
  ElMessageBox.confirm('请确认是否删除？', '提示', {type: 'warning'}).then(() => {
    const index = display.ruleList
      .findIndex(item => item.id ? item.id === data.id : item.rowFlag === data.rowFlag);
    display.ruleList.splice(index, 1);
  }).catch(() => {});
};

const component = ref({
  '单行文本框': 'ac-input',
  '密码文本框': 'ac-password',
  '多行文本框': 'ac-input',
  '富文本框': 'ac-input',
  '单选框': 'ac-select',
  '下拉框': 'ac-select',
  '多选框': 'ac-select',
  '多选下拉框': 'ac-select',
  '开关': 'ac-switch',
  '字符': 'ac-input',
  '整数': 'ac-input',
  '小数': 'ac-number',
  '日期': 'ac-date',
  '时间': 'ac-datetime',
  '图片': 'ac-image',
  '视频': 'ac-video',
  '附件': 'ac-affix',
  '下拉选择': 'ac-remote-select',
  '树形控件': 'ac-dm-tree',
  '区划树': 'ac-region-tree',
  '单位树': 'ac-unit-tree',
  '企业树': 'ac-entp-tree',
  '部门树': 'ac-organization-tree',
  '人员树': 'ac-employee-tree',
  '字典树': 'ac-dict-tree',
  '字典开关': 'ac-dict-switch',
  '字典单选框': 'ac-dict-select',
  '字典下拉框': 'ac-dict-select',
});
const getComponent = (fieldName) => {
  const field = fieldList.value.find(item => item.fieldName === fieldName);
  if (!field) return 'ac-input';

  if (field.fieldType === '字符') {
    if (field.enumerate === '1' && field.enumerateType) {
      return component.value[field.enumerateType];
    } else if (field.inputType) {
      return component.value[field.inputType];
    } else {
      return 'ac-input';
    }
  } else if ("整数、小数、日期、时间、图片、视频、附件".indexOf(field.fieldType) >= 0) {
    return component.value[field.fieldType];
  } else if (field.fieldType === '联动') {
    if (field.relevanceType === '数据模型') {
      return component.value['树形控件'];
    } else {
      return component.value[field.relevanceType];
    }
  } else if (field.fieldType === '大文本') {
    return component.value[field.inputType];
  }

  return 'ac-input';
};

const getOptions = (fieldName) => {
  const field = fieldList.value.find(item => item.fieldName === fieldName);
  if (!field) return {};

  if (field.fieldType === '字符') {
    if (field.autoCreate === '1') {
      return {};
    } else if (field.enumerate === '1') {
      return {options: field.enumerateValue || ''};
    } else {
      return {max: field.fieldSize || 100};
    }
  } else if ("整数、小数".indexOf(field.fieldType) >= 0) {
    return {
      point: "整数" === field.fieldType ? 0 : field.fieldPrecision || 0,
      max: field.maxValue, min: field.minValue
    };
  } else if ("日期".indexOf(field.fieldType) >= 0) {
    return {format: field.format || undefined, valueFormat: field.format || undefined};
  } else if (field.fieldType === '图片') {
    return {limit: 1, maxSize: field.imageMaxSize};
  } else if (field.fieldType === '视频') {
    return {limit: 1, maxSize: field.imageMaxSize};
  } else if (field.fieldType === '联动') {
    if (field.relevanceType === '数据模型') {
      const relevanceList = field.relevanceList || [];
      return {
        dataFieldId: field.id,
        leafSelect: relevanceList.length > 1,
        typeSelect: relevanceList[relevanceList.length - 1].id
      };
    } else {
      return {dictCode: field.relevanceDict || ''};
    }
  }

  return {};
};

const submitData = () => {
  dataForm.value && dataForm.value.validate((valid) => {
    if (valid) {
      ElMessageBox.confirm("请确认是否提交？", "提示", {type: "info"}).then(() => {
        loading.showLoading();
        api.post('/system/dataForm/save', formData.value).then(res => {
          ElMessage.success(res.message);
          emit('afterSubmit');
          loading.hideLoading();
        }).catch(() => loading.hideLoading());
      }).catch(() => {});
    } else {
      ElMessage.error('数据录入不正确，请重新检查！');
    }
  });
};

const loadDataField = (modelId) => {
  fieldList.value = [];
  fieldIdOptions.value = [];
  fieldNameOptions.value = [];

  api.post('/system/dataField/queryList', {modelId: modelId}).then(res => {
    fieldList.value = res.data || [];
    fieldList.value.forEach(field => {
      fieldIdOptions.value.push({key: field.id, value: field.showName});
      fieldNameOptions.value.push({key: field.fieldName, value: field.showName});
    });
    refreshFieldName();
  });
};

const refreshFieldName = () => {
  formData.value.modelList.forEach(model => {
    model.fieldList.forEach(field => {
      const find = fieldList.value.find(item => item.id === field.fieldId);
      if (find) {
        field.fieldName = find.fieldName;
      } else {
        field.fieldName = '';
      }
    });
  });
};

watch(() => props.options, (options) => {
  init(options || {});
});

onMounted(() => {
  init(props.options || {});
});

scriptTips.value = "\
此页面脚本为页面执行的javascript脚本。可声名的函数：\n\
\n\
context.getUser()：获取用户数据\n\
context.getOrg()：获取组织机构数据\n\
context.getPageData()：获取整个页面数据\n\
context.runScript(id, params)：id：脚本id，params：参数\n\
\n\
/*\n\
 * 表单初始化时执行此函数（必须是以function开头声名的函数，异步函数时在function前加上: async）\n\
 * @param args为页面参数\n\
 */\n\
function initData(formData, context)\n\
\n\
/*\n\
 * 字段名称对应值变更后执行此函数（必须是以function开头声名的函数）\n\
 * @param data为表单数据显示后的值\n\
 * @return object 以Object方式返回修改后的值\n\
 */\n\
function change_字段名称(data, context)\n\
\n\
/*\n\
 * 表单数据变更后执行此函数（必须是以function开头声名的函数）\n\
 * @param data为表单数据显示后的值\n\
 * @return object 以Object方式返回修改后的值\n\
 */\n\
function change(data, context)\n\
\n\
/*\n\
 * 字段名称对应值变更时执行此校验函数（必须是以function开头声名的函数）\n\
 * @param data为表单数据显示后的值\n\
 */\n\
function validate_字段名称(data, callback, context)\n\
\n\
/*\n\
 * 表单提交前执行此校验函数（必须是以function开头声名的函数）\n\
 * @param data为表单数据显示后的值\n\
 * @return boolean 通过校验返回true，否则返回Error\n\
 */\n\
function validate(data, context)\n\
\n\
示例：\n\
function change(data, context) {\n\
  const result = {};\n\
  if (data['age'] < 1) {\n\
    result['stage'] = '婴儿';\n\
  } else if (data['age'] < 3) {\n\
    result['stage'] = '幼儿';\n\
  } else if (data['age'] < 59) {\n\
    result['stage'] = '中年';\n\
  } else if (data['age'] >= 60) {\n\
    result['stage'] = '老年';\n\
  } else if (data['age'] >= 200) {\n\
    return new Error('年龄错误！');\n\
  }\n\
  return result;\n\
}\n\
\n\
function validate_age(data, callback, context) {\n\
  if (data['age'] >= 200) {\n\
    callback(new Error('年龄不能越过200'));\n\
  } else {\n\
    callback();\n\
  }\n\
}\n\
\n\
function validate(data, context) {\n\
  if (data['age'] >= 200) {\n\
    return new Error('年龄不能越过200');\n\
  } else {\n\
    return true;\n\
  }\n\
}";

defineExpose({submitData});
</script>

<style scoped lang="scss">
.script-tips-box {
  width: 800px;
  height: 500px!important;
  border: none!important;
  :deep(.el-textarea__inner) {
    height: 100%!important;
    background: transparent!important;
    border: none!important;
    box-shadow: 0 0 0 0!important;
    font-size: 16px;
    color: #d2cfcf !important;
  }
}
.script-box {
  height: 1px;
  flex-grow: 1;
  display: flex;
  flex-direction: row;
  .script-left-box {
    width: 1px;
    flex-grow: 1;
  }
  .script-right-box {
    width: 350px;
    display: flex;
    flex-direction: column;
    .field-box {
      padding: 5px 10px;
      background: rgb(40, 42, 54);
      height: 1px;
      flex-grow: 1;
      overflow: auto;
      .field-item {
        color: #f1fa8c;
        font-size: 14px;
        line-height: 22px;
      }
    }
  }
}
.param-item {
  display: flex;
  flex-direction: row;
  .param-field {
    width: 220px;
    display: flex;
    flex-direction: row;
    flex-shrink: 0;
  }
  .param-split {
    width: 44px;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 20px;
  }
  .param-page {
    flex-grow: 1;
  }
}
.param-item+.param-item {
  margin-top: 5px;
}
</style>